package Algorithm.interview;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author self
 * @Date 2024/9/7 13:47
 * @Describe 实现一个加权负载均衡算法
 */

/*每个服务器分配一个权重，权重越大的服务器会得到更多的请求。
        通过轮询的方式，每次选择权重最高的服务器进行请求分发。
        动态更新权重，以达到均匀分配请求的目的。*/
/*    权重机制的核心
            当我们增加每台服务器的 currentWeight 时，它的权重会逐渐积累，
            权重大的服务器会更快积累到最高，优先被选中。然而，选中后必须减去总权重，
            这样可以给其他服务器一个机会在下一轮轮询中积累到最高权重，从而被选中。*/
public class WeightedRoundRobin {
    private List<Server> servers; // 服务器列表
    private int totalWeight; // 所有服务器权重之和

    public WeightedRoundRobin(List<Server> servers) {
        this.servers = servers;
        this.totalWeight = servers.stream().mapToInt(s -> s.weight).sum();
    }

    // 选择下一台服务器
    public Server getNextServer() {
        Server selectedServer = null;
        int maxWeight = Integer.MIN_VALUE;

        // 查找具有最大当前权重的服务器
        for (Server server : servers) {
            // 累加服务器的当前权重
            server.currentWeight += server.weight;

            // 寻找当前权重最大的服务器
            if (server.currentWeight > maxWeight) {
                maxWeight = server.currentWeight;
                selectedServer = server;
            }
        }

        // 选中的服务器的当前权重减去总权重
        if (selectedServer != null) {
            selectedServer.currentWeight -= totalWeight;
        }

        return selectedServer;
    }

    static class Server {
        String name;
        int weight; // 服务器的权重
        int currentWeight; // 当前权重，用于算法中的临时计算

        public Server(String name, int weight) {
            this.name = name;
            this.weight = weight;
            this.currentWeight = 0; // 初始化当前权重为0
        }

        @Override
        public String toString() {
            return name;
        }
    }

    public static void main(String[] args) {
        // 创建一些服务器并为其分配权重
        List<Server> servers = new ArrayList<>();
        servers.add(new Server("ServerA", 5));
        servers.add(new Server("ServerB", 1));
        servers.add(new Server("ServerC", 1));

        WeightedRoundRobin loadBalancer = new WeightedRoundRobin(servers);

        // 模拟分发 10 次请求
        for (int i = 0; i < 10; i++) {
            Server server = loadBalancer.getNextServer();
            System.out.println("Request " + (i + 1) + " is assigned to " + server);
        }
    }
}
